import './modules/sw-keep-alive.js';
// import './modules/sw-nativemessage.js';
import './modules/sw-offscreen.js';
import { generateFunc, runtimeEvaluateAsync } from './modules/sw-debugger.js';
import './modules/sw-userScripts.js';

class UIAError extends Error {
    constructor(code, message, multiLangCode) {
        super(message || '');
        this.code = code;
        this.multiLangCode = multiLangCode;
    }
}

class TabsApi {
    createPromise(createProperties) {
        return new Promise((resolve) => {
            chrome.tabs.create(createProperties, (tab) => {
                resolve(tab);
            });
        });
    }

    queryPromise(queryInfo) {
        return new Promise((resolve) => {
            chrome.tabs.query(queryInfo, (tabs) => {
                resolve(tabs);
            });
        });
    }

    updatePromise(tabId, updateInfo) {
        return new Promise((resolve) => {
            chrome.tabs.update(tabId, updateInfo, (tab) => {
                resolve(tab);
            });
        });
    }

    getPromise(tabId) {
        return new Promise((resolve) => {
            chrome.tabs.get(tabId, (tab) => {
                resolve(tab);
            });
        });
    }

    reloadPromise(tabId, bypassCache) {
        return new Promise((resolve) => {
            chrome.tabs.reload(
                tabId,
                {
                    bypassCache,
                },
                () => {
                    resolve();
                },
            );
        });
    }

    highlightPromise(highlightInfo) {
        return new Promise((resolve) => {
            chrome.tabs.highlight(highlightInfo, (tab) => {
                resolve(tab);
            });
        });
    }

    goForwardPromise(tabId) {
        return new Promise((resolve) => {
            chrome.tabs.goForward(tabId, () => {
                resolve();
            });
        });
    }

    goBackPromise(tabId) {
        return new Promise((resolve) => {
            chrome.tabs.goBack(tabId, () => {
                resolve();
            });
        });
    }

    removePromise(tabIds) {
        return new Promise((resolve) => {
            chrome.tabs.remove(tabIds, () => {
                resolve();
            });
        });
    }

    getZoomPromise(tabId) {
        return new Promise((resolve) => {
            chrome.tabs.getZoom(tabId, (zoomFactor) => {
                resolve(zoomFactor);
            });
        });
    }
}

// v3 注入脚本
class ScriptingApi {
    //  v2 v3 执行脚本，脚本类型code (v3 code代码注入使用，注入后直接使用executeFuncOnFrame v2 执行命令使用)
    async executeCodeOnFrameAsync(tabId, frameId, code, args = []) {
        // v3 先将code包装为func再执行
        const { result } = await runtimeEvaluateAsync(code);
        return await this.executeFuncOnFramePromise(tabId, frameId, result, args);
    }

    /**
     * v3 执行脚本，脚本类型func
     */
    executeFuncOnFramePromise(tabId, frameId, func, args = []) {
        return new Promise((resolve, reject) => {
            chrome.scripting.executeScript({ target: { tabId: Number(tabId), frameIds: [frameId] }, func, args }, (result) => {
                if (chrome.runtime.lastError) {
                    reject(new UIAError(chrome.runtime.lastError.message));
                } else if (Array.isArray(result) && result.length === 1) {
                    resolve(result[0]?.result);
                } else {
                    reject(new UIAError(`${frameId} execute script fail.`));
                }
            });
        });
    }

    // 注入脚本文件
    executeContentToFramePromise(tabId, frameId) {
        return new Promise((resolve, reject) => {
            chrome.scripting.executeScript(
                {
                    target: {
                        tabId: Number(tabId),
                        frameIds: [frameId],
                    },
                    files: ['resource/Content-Script.js'],
                    injectImmediately: true,
                    world: 'ISOLATED',
                },
                (result) => {
                    if (chrome.runtime.lastError) {
                        reject(new UIAError(chrome.runtime.lastError.message));
                    } else if (Array.isArray(result) && result.length === 1) {
                        resolve(result[0]?.result);
                    } else {
                        reject(new UIAError(`${frameId} execute script fail.`));
                    }
                },
            );
        });
    }

    // v3 在全部frame中执行脚本，脚本类型 func
    executeFuncOnAllFramesPromise(tabId, func, args = []) {
        return new Promise((resolve, reject) => {
            chrome.scripting.executeScript({ target: { tabId: Number(tabId), allFrames: true }, func, args }, (result) => {
                if (chrome.runtime.lastError) {
                    reject(new UIAError(chrome.runtime.lastError.message));
                } else {
                    resolve(result);
                }
            });
        });
    }
}

// 注入代码
runtimeEvaluateAsync('globalThis.a="a"');

chrome.webNavigation.onCompleted.addListener(async ({ tabId, url, frameId }) => {
    const scriptString = `
document.body.style.backgroundColor = 'lightgreen';
console.log('脚本注入成功!');
`;
    const func = await generateFunc(scriptString);
    console.log(func, 'func');
    new ScriptingApi().executeFuncOnFramePromise(tabId, 0, func, []);
});
